package edu.udo.sopra10.chaturaji.gui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Rectangle;
import java.util.HashMap;

import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;

import se.datadosen.component.RiverLayout;
import edu.udo.sopra10.chaturaji.gui.util.WrappedFlowLayout;

/**
 * Status panel that displays player related data and the current status during
 * the game. Also features a list of all captured pieces.
 * 
 * @author Patrick Westerhoff
 * 
 */
public class PlayerStatusPanel extends JPanel
{
	private static final long serialVersionUID = 6634924616436831100L;
	private static final int PADDING = 2;
	
	private static HashMap<Byte, Color> COLORS = new HashMap<Byte, Color>( 4 );
	
	static
	{
		COLORS.put( (byte) 0, new Color( 0xACA237 ) );
		COLORS.put( (byte) 1, new Color( 0x4C2C75 ) );
		COLORS.put( (byte) 2, new Color( 0xAA373A ) );
		COLORS.put( (byte) 3, new Color( 0x318B2D ) );
	}
	
	private JPanel playerPanel;
	private JPanel piecesPanel;
	
	private JLabel playerName;
	private JLabel playerType;
	private JLabel playerScore;
	
	private Color playerColor;
	private int score;
	
	
	/**
	 * Constructs a PlayerStatusPanel with the specified titles and color.
	 * 
	 * @param title the player's main title or name.
	 * @param subtitle the player's subtitle.
	 * @param playerId the player id.
	 */
	public PlayerStatusPanel ( String title, String subtitle, byte playerId )
	{
		super( new RiverLayout( PADDING, PADDING ) );
		Font defaultFont = this.getFont();
		
		Dimension d;
		playerColor = COLORS.get( playerId );
		
		/* player panel */
		playerName = new JLabel( title );
		playerName.setFont( defaultFont.deriveFont( defaultFont.getSize2D() + 6 ) );
		
		playerType = new JLabel( subtitle );
		playerType.setFont( defaultFont.deriveFont( defaultFont.getSize2D() - 2 ) );
		playerType.setForeground( Color.GRAY );
		
		playerScore = new JLabel( "" );
		playerScore.setFont( defaultFont.deriveFont( defaultFont.getSize2D() + 10 ) );
		playerScore.setHorizontalAlignment( JLabel.RIGHT );
		
		// absolute positioning
		d = playerName.getPreferredSize();
		playerName.setBounds( 10 + PADDING, 0, d.width, d.height );
		
		d = playerType.getPreferredSize();
		playerType.setBounds( 20, playerName.getHeight() - 7, d.width, d.height );
		
		// player panel
		playerPanel = new JPanel( null );
		playerPanel.add( playerName );
		playerPanel.add( playerType );
		playerPanel.add( playerScore );
		playerPanel.setBorder( BorderFactory.createMatteBorder( 0, 10, 2, 0, playerColor ) );
		
		d = new Dimension( Short.MAX_VALUE, (int) playerType.getBounds().getMaxY() + PADDING );
		playerPanel.setPreferredSize( d );
		
		/* captured pieces panel */
		piecesPanel = new JPanel( new WrappedFlowLayout( FlowLayout.LEADING, 1, 1 ) );
		piecesPanel.setBorder( BorderFactory.createEmptyBorder( 0, 5, 0, 0 ) );
		
		/* main */
		this.add( "hfill", playerPanel );
		this.add( "hfill br", piecesPanel );
		this.setPreferredSize( new Dimension( 200, Short.MAX_VALUE ) );
	}
	
	/**
	 * Constructs a PlayerStatusPanel with the specified title and color, and
	 * an empty subtitle.
	 * 
	 * @param title the player's main title or name.
	 * @param playerId the player id.
	 */
	public PlayerStatusPanel ( String title, byte playerId )
	{
		this( title, "", playerId );
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void doLayout ()
	{
		super.doLayout();
		
		// update size
		Rectangle r = piecesPanel.getBounds();
		this.setSize( new Dimension( this.getWidth(), r.y + r.height + PADDING ) );
		this.setPreferredSize( this.getSize() );
		
		// update absolute layout
		Dimension d = playerScore.getPreferredSize();
		playerScore.setBounds( playerPanel.getWidth() - d.width, 0, d.width, d.height );
	}
	
	/**
	 * Updates the labels.
	 * 
	 * @param title the player's main title or name.
	 * @param subtitle the player's subtitle.
	 */
	public void updateLabels ( String title, String subtitle )
	{
		Dimension d;
		
		// update texts
		playerName.setText( title );
		playerType.setText( subtitle );
		
		// absolute positioning
		d = playerName.getPreferredSize();
		playerName.setBounds( 10 + PADDING, 0, d.width, d.height );
		
		d = playerType.getPreferredSize();
		playerType.setBounds( 20, playerName.getHeight() - 7, d.width, d.height );
	}
	
	/**
	 * Adds a captured piece to the displayed list.
	 * 
	 * @param piece the piece to add.
	 */
	public void addPiece ( SquarePanel piece )
	{
		piece.setForcedPreferredSize( new Dimension( 16, 16 ) );
		piecesPanel.add( piece );
	}
	
	/**
	 * Removes all captured pieces in the displayed list.
	 * 
	 */
	public void removeAllPieces ()
	{
		piecesPanel.removeAll();
	}
	
	/**
	 * Returns the name of the player.
	 * 
	 * @return the player name.
	 */
	public String getPlayerName ()
	{
		return playerName.getText();
	}
	
	/**
	 * Returns the player type of the player.
	 * 
	 * @return the player type.
	 */
	public String getPlayerType ()
	{
		return playerType.getText();
	}
	
	/**
	 * Returns the color of the player.
	 * 
	 * @return the player color.
	 */
	public Color getPlayerColor ()
	{
		return playerColor;
	}
	
	/**
	 * Returns the current score of the player.
	 * 
	 * @return the score.
	 */
	public int getScore ()
	{
		return score;
	}
	
	/**
	 * Sets the current score of the player.
	 * 
	 * @param score the score to set.
	 */
	public void setScore ( int score )
	{
		this.score = score;
		playerScore.setText( String.valueOf( score ) );
	}
	
	// TODO: add highlight switch (if it's a player's turn)
	// TODO: add dice?
	
	/**
	 * Returns the color associated to the given player.
	 * 
	 * @param playerId the player id.
	 * @return the player's color.
	 */
	public static Color getPlayerColor ( byte playerId )
	{
		return COLORS.get( playerId );
	}
}